#include <fstream>
#include <vector>
#include <bitset>
#include <algorithm>

int main()
{
	//Default variables
	std::vector<uint32_t> polynomial = {1, 2, 3, 5, 6, 8, 15, 19, 28, 33, 38};
	std::vector<std::bitset<8>> reg = {0x64, 0xE9, 0x89, 0x1A, 0x5B, 0xC5, 0xDE}; // {0b01100100, 0b11101001, 0b10001001, 0b00011010, 0b01011011, 0b11000101, 0b11011110};

	uint64_t file_size = 1024*1024;
	std::ofstream file("output.dat");

	//Cached variables (for performance)
	const auto bits_in_reg = reg.size() * 8;
	const auto reg_size = reg.size();

	//Algorithm
	std::bitset<8> byte = 0;
	for (size_t i = 0; i < file_size; i++) {

		byte = reg.back();
		file << (uint8_t) byte.to_ulong();

		for(size_t bit = 0; bit < 8; bit++) {
			bool shift_bit = 0;
			for (auto &elem : polynomial) {
				auto _elem = elem + bit;
				if (_elem >= bits_in_reg)
				{
					shift_bit ^= byte[_elem % bits_in_reg];
				}
				else
				{
					size_t reg_element = _elem / 8;
					size_t reg_bit = _elem % 8;
					shift_bit ^= reg[reg_size - 1 - reg_element][reg_bit];
				}
			}

			byte[bit] = shift_bit;
		}

		reg.pop_back();
		reg.insert(reg.begin(), byte);
	}

	file.close();

	return 0;
}
